package com.ruoyi.framework.aspectj;

import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Date;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * @description 操作数据库时设置用户
 */
@Aspect
@Component
public class AutoSetUserAspect {

	@Pointcut("execution(* com.ruoyi.*.mapper.*.insert*(..))")
	public void add() {
	}

	@Pointcut("execution(* com.ruoyi.*.mapper.*.insertLogininfor(..))")
	public void addLogin() {
	}

	@Pointcut("execution(* com.ruoyi.*.mapper.*.updateUser*(..))")
	public void updateLogin() {
	}
	@Pointcut("execution(* com.ruoyi.*.mapper.*.update*(..))")
	public void update() {
	}

	@Before("add() && !addLogin()")
	public void doAddBefore(JoinPoint point) {
		Object[] param = point.getArgs();
		setAddUser(param);
	}

	@Before("update() && !updateLogin()")
	public void doUpdateBefore(JoinPoint point) {
		Object[] param = point.getArgs();
		setUpdateUser(param);
	}

	private void setAddUser(Object[] paramList) {
		this.setUser(paramList, param -> {
			Authentication auth = SecurityUtils.getAuthentication();
			String userName = "admin";
			if (auth != null) {
				LoginUser loginUser = SecurityUtils.getLoginUser();
				userName = loginUser.getUsername();
			}

			param.setCreateTime(new Date());
			param.setCreateBy(userName);
			param.setUpdateTime(new Date());
			param.setUpdateBy(userName);
		});
	}

	private void setUpdateUser(Object[] paramList) {
		this.setUser(paramList, param -> {
			Authentication auth = SecurityUtils.getAuthentication();
			String userName = "admin";
			if (auth != null) {
				LoginUser loginUser = SecurityUtils.getLoginUser();
				userName = loginUser.getUsername();
			}
			LoginUser loginUser = SecurityUtils.getLoginUser();
			param.setUpdateTime(new Date());
			param.setUpdateBy(userName);
		});
	}

	private void setUser(Object[] paramList, Consumer<BaseEntity> consumer) {
		for (Object param : paramList) {
			if (Objects.isNull(param)) {
				continue;
			}
			if (param instanceof BaseEntity) {
				consumer.accept((BaseEntity) param);
			} else if (param.getClass().isArray()) {
				Object[] objsNew = (Object[]) param;
				setAddUser(objsNew);
			} else if (param instanceof Collection) {
				Collection<?> c = (Collection<?>) param;
				setAddUser(c.toArray());
			}
		}
	}
}
